// ActivationManager.java
package org.zjx.manager;

import com.sun.jna.platform.win32.WinDef;
import lombok.extern.slf4j.Slf4j;
import org.zjx.core.IWindow;
import org.zjx.util.HwndUtil;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 全局激活管理器 - 改进超时处理和资源管理
 */
@Slf4j
public class ActivationManager {
    private static final Lock activationLock = new ReentrantLock(true);
    private static final Condition activationReleased = activationLock.newCondition();
    private static final AtomicReference<IWindow> activeWindowRef = new AtomicReference<>(null);

    // 关键改进：添加超时和失效检查
    private static final long REQUEST_TIMEOUT = 30000; // 30秒请求超时
    private static final long WINDOW_CHECK_INTERVAL = 1000; // 1秒检查一次窗口状态

    private ActivationManager() {
    }

    public static boolean requestActivation(IWindow requestingWindow) {
        if (requestingWindow == null) {
            throw new IllegalArgumentException("请求窗口不能为空");
        }

        // 快速路径
        if (activeWindowRef.get() == requestingWindow) {
            return true;
        }

        activationLock.lock();
        try {
            long startTime = System.currentTimeMillis();
            long remainingTime = REQUEST_TIMEOUT;

            while (activeWindowRef.get() != null && activeWindowRef.get() != requestingWindow) {
                // 关键改进1：检查超时
                if (remainingTime <= 0) {
                    log.error("[激活] 请求超时: {}", requestingWindow.getId());
                    return false;
                }

                // 关键改进2：检查当前激活窗口是否失效
                IWindow currentActive = activeWindowRef.get();
                if (currentActive != null && !currentActive.isValid()) {
                    log.warn("[激活] 当前激活窗口已失效，自动释放: {}", currentActive.getId());
                    activeWindowRef.set(null);
                    activationReleased.signalAll();
                    break;
                }

                try {
                    // 关键改进3：使用带超时的等待，避免永久阻塞
                    boolean signaled = activationReleased.await(
                            Math.min(remainingTime, WINDOW_CHECK_INTERVAL), TimeUnit.MILLISECONDS);

                    // 更新剩余时间
                    long elapsed = System.currentTimeMillis() - startTime;
                    remainingTime = REQUEST_TIMEOUT - elapsed;

                } catch (InterruptedException e) {
                    log.warn("[激活] 请求被中断: {}", requestingWindow.getId());
                    Thread.currentThread().interrupt();
                    return false;
                }
            }

            // 设置激活窗口
            activeWindowRef.set(requestingWindow);

            HwndUtil.preposition(requestingWindow.getHwnd());
            return true;

        } finally {
            activationLock.unlock();
        }
    }

    public static void releaseActivation(IWindow window) {
        if (window == null) return;

        activationLock.lock();
        try {
            IWindow currentActive = activeWindowRef.get();
            if (currentActive == window) {
                activeWindowRef.set(null);
                activationReleased.signalAll();
            }
        } finally {
            activationLock.unlock();
        }
    }

    // 关键改进4：添加强制释放方法，用于处理异常情况
    public static void forceReleaseIfStuck() {
        activationLock.lock();
        try {
            IWindow currentActive = activeWindowRef.get();
            if (currentActive != null) {
                // 检查窗口是否长时间占用激活权（超过2倍超时时间）
                // 这里可以添加更复杂的检测逻辑
                log.warn("[激活] 强制释放可能卡住的激活窗口: {}", currentActive.getId());
                activeWindowRef.set(null);
                activationReleased.signalAll();
            }
        } finally {
            activationLock.unlock();
        }
    }

    public static boolean isActiveWindow(IWindow window) {
        IWindow activeWindow = activeWindowRef.get();
        return activeWindow != null && activeWindow == window;
    }

    public static IWindow getActiveWindow() {
        return activeWindowRef.get();
    }
}